/**
 * Project: Useful Programs <br>
 * Package: tools
 */
package org.leumasjaffe.io;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.Serializable;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

import biz.source_code.base64Coder.Base64Coder;

/**
 * Class .SerializeString in file SerializeString.java <br>
 * 
 * @author OscarRyz
 * Created on: Aug 17, 2012
 * 
 */
@NonNullByDefault
public class SerializeString {	
	/** 
	 * Read the object from Base64 string.
	 * @param s The serialized (encoded) String
	 * @return Returns the object that was serialized
	 * @throws IOException If there is an In/Out error reading the byte array
	 * @throws ClassNotFoundException If the class that the serialized String represents cannot exist
	 */
	public static @Nullable Object fromString(String s) throws IOException, ClassNotFoundException {
        byte[] data = Base64Coder.decode(s);
        try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
        	return ois.readObject();
        }
    }

	/**
	 * Write the object to a Base64 string.
	 * @param o The Object to be serialized
	 * @return Returns the encoded String representing the object in its present state
	 * @throws IOException If there is an In/Out error reading the object
	 */
    public static String toString(Serializable o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
        	oos.writeObject(o);
        	return new String(Base64Coder.encode(baos.toByteArray()));
        }
    }
    
    /**
     * 
     * @param path The location to write the file
     * @param o The Object to be serialized
     */
    public static void toFile(String path, Serializable o) {
    	toFile(new File(path), o);
    }
    
    /**
     * 
     * @param file The location to write the file
     * @param o The Object to be serialized
     */
    public static void toFile(File file, Serializable o) {
    	try (PrintStream ps = new PrintStream(file)) {
			ps.println(toString(o));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
    }
    
    /**
     * 
     * @param path The location of the file
     * @return Returns the object that was serialized
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static @Nullable Object fromFile(String path) throws IOException, ClassNotFoundException {
    	return fromFile(new File(path));
    }
    
    /**
     * 
     * @param file The location of the file
     * @return Returns the object that was serialized
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @SuppressWarnings("null")
	public static @Nullable Object fromFile(File file) throws IOException, ClassNotFoundException {
		String output = "";
		try (FileInputStream fis = new FileInputStream(file);
			DataInputStream dis = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(dis))) {
			String strLine = "";
			while ((strLine = br.readLine()) != null)
				output += strLine;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return fromString(output);
    }
    
}